<?php

/* ========================================================================= */
/* This file is part of the HypnoPHP Framework Library                       */
/* Copyright (c) 2009-2010, Radu Buzea                                       */
/* ========================================================================= */

/**
* @author Radu Buzea
* @copyright Copyright (c) 2009-2010, Radu Buzea (www.hypnosis.ro)
* @license GNU Lesser General Public License (www.gnu.org/copyleft/lesser.html)
* @package HypnoPHP
* @category Core
* @version 1.0.3
*/

defined('HYPNOPHP_APPLICATION') or
die("Cannot use <i>" . basename(__FILE__) . "</i> outside HypnoPHP Application");

// ============================================================================
// Final class: HAuthentication
// ============================================================================

final class HAuthentication extends HBaseObject
{

	protected $__username = '';
	protected $__password = '';
	protected $__md5_mode = true;
	protected $__auth_callback_class = '';
	protected $__auth_callback_method = '';

	# ###########################################################################

	/**
	* Initialize object properties
	*
	*	@return void
	*/
	public function __initialize()
	{
		$this->__username = '';
		$this->__password = '';
		$md5_mode_auth = HApplication::getConfig('md5_mode_authentication');
		$this->__md5_mode = (is_bool($md5_mode_auth) && $md5_mode_auth);
	}

	# ###########################################################################

	/**
	* Get the registered username - property getter method
	*
	*	@return string
	*/
	public function __get_username()
	{
		if ($this->__username == '') { return ''; }
		else { return $this->__username; }
	}

	# ###########################################################################

	/**
	* Get the registered password - property getter method
	*
	* @return string
	*/
	public function __get_password()
	{
		if ($this->__password == '') { return ''; }
		else if ($this->__md5_mode) { return md5($this->__password); }
		else { return $this->__password; }
	}

	# ###########################################################################

	/**
	* Register username - property setter method
	*
	* @param string $value The username
	* @return void
	*/
	public function __set_username($value = '')
	{
		$this->__username = trim($value);
	}

	# ###########################################################################

	/**
	* Register password - property setter method
	*
	* @param string $value The password
	* @return void
	*/
	public function registerPassword($value = '')
	{
		$this->__password = trim($value);
	}

	# ###########################################################################

	/**
	* Register callback authentication method
	*
	* @param string $class_name The class name that contains the authentication method or null...
	* @param string $method_name The function name that checks the credentials
	* @return void
	*/
	public function registerAuthCallback($class_name = '', $method_name = '')
	{
		if (is_string($class_name) && $class_name != '' && $this->__checkVarName($class_name)) {
			$this->__auth_callback_class = $class_name;
		}
		if (is_string($method_name) && $method_name != '' && $this->__checkVarName($method_name)) {
			$this->__auth_callback_method = $method_name;
		}
	}

	# ###########################################################################

	/**
	* Use md5 hash for password encoding - property getter method
	*
	* @return bool
	*/
	public function __get_md5_encode()
	{
		return $this->__md5_mode;
	}

	# ###########################################################################

	/**
	* Use md5 hash for password encoding - property setter method
	*
	* @param bool
	* @return void
	*/
	public function __set_md5_encode($value = false)
	{
		$this->__md5_mode = boolval($value);
	}

	# ###########################################################################

	/**
	* Check credentials - username and password are set
	*
	* @param string $username The username
	* @param string $password The password
	* @return bool
	*/
	public function checkCredentials($username = '', $password = '')
	{
		if ($this->__username != '' && $this->__password != '') {
			if ($username != $this->__username) { return false; }
			if ($this->__md5_mode) {
				$password = md5($password);
				$md5_password = md5($this->__password);
				return ($this->__password == $password || $md5_password == $password);
			}
			return ($this->__password == $password);
		} else if ($this->__auth_callback_method != '') {
			if ($this->__auth_callback_class != '') {
				$call_param = array($this->__auth_callback_class, $this->__auth_callback_method);
			} else {
				$call_param = $this->__auth_callback_method;
			}
			return call_user_func($call_param, $username, $password);
		}
		return false;
	}

	# ###########################################################################

	/**
	* Check authentication - static method
	*
	* @param string $username The username
	* @param string $password The password
	* @param string $login_redir (optional) The URL addres of the login form (redirect)
	* @return bool
	*/
	public static function check($username = '', $password = '', $login_redir = '')
	{
		$auth = self::getInstance();
		$auth_user = HSession::getVar('authuser');
		$auth_pass = HSession::getVar('authpass');
		if (!is_null($auth_user) && !is_null($auth_pass)) {
			$logout = HRequest::params('logout');
			if ($logout) {
				HSession::unregister('authuser');
				HSession::unregister('authpass');
				$auth->username = '';
				$auth->password = '';
				return false;
			} else {
				$auth->username = $auth_user;
				$auth->password = $auth_pass;
			}
		}
		$result = $auth->checkCredentials($username, $password);
		if (!$result) {
			if ($login_redir != '') { HResponse::redirect($login_redir); }
			else {
				$php_auth_user = HRequest::server('PHP_AUTH_USER');
				if (is_null($php_auth_user)) {
					$realm = HApplication::getConfig('authentication_realm');
					if (!is_string($realm)) { $realm = ''; }
					HResponse::http_authentication($realm);
				} else {
					$username = HRequest::server('PHP_AUTH_USER');
					$password = HRequest::server('PHP_AUTH_PW');
					$result = $auth->checkCredentials($username, $password);
				}
			}
		}
		if ($result) {
			HSession::register('authuser', $username);
			HSession::register('authpass', $password);
		}
		return $result;
	}

	# ###########################################################################

	/**
	* Get the request object instance (singleton)
	*
	* @return HAuthentication
	*/
	public static function getInstance()
	{
		return self::singleton(__CLASS__);
	}

	# ###########################################################################

}
